home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / AmiTCP30b2.lha / src / amitcp / kern / amiga_time.c < prev    next >
C/C++ Source or Header  |  1993-08-12  |  10KB  |  343 lines

  1. RCS_ID_C="$Id: amiga_time.c,v 1.15 1993/06/04 11:16:15 jraja Exp $";
  2. /*
  3.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
  4.  *                    Helsinki University of Technology, Finland.
  5.  *                    All rights reserved.
  6.  *
  7.  * $Log: amiga_time.c,v $
  8.  * Revision 1.15  1993/06/04  11:16:15  jraja
  9.  * Fixes for first public release.
  10.  *
  11.  * Revision 1.14  1993/05/17  01:07:47  ppessi
  12.  * Changed RCS version.
  13.  *
  14.  * Revision 1.13  1993/05/14  23:14:02  ppessi
  15.  * Updated to the latest ARP includes.
  16.  *
  17.  * Revision 1.12  93/04/19  02:23:18  02:23:18  ppessi (Pekka Pessi)
  18.  * Removed arp proto file
  19.  * 
  20.  * Revision 1.11  93/04/06  15:15:45  15:15:45  jraja (Jarno Tapio Rajahalme)
  21.  * Changed spl function return value storage to spl_t,
  22.  * changed bcopys and bzeros to aligned and/or const when possible,
  23.  * added inclusion of conf.h to every .c file.
  24.  * 
  25.  * Revision 1.10  93/03/15  14:41:00  14:41:00  jraja (Jarno Tapio Rajahalme)
  26.  * Changed the initialization of timeoutRequests to explicitly copy needed 
  27.  * structure fields from the timerIORequest. Node type is initialized to
  28.  * NT_UNKNOWN to indicate thet request has never been used.
  29.  * 
  30.  * Revision 1.9  93/03/13  17:12:59  17:12:59  ppessi (Pekka Pessi)
  31.  * Fixed bugs with variable initializations. Works with UDP.
  32.  * 
  33.  * Revision 1.8  93/03/10  23:08:12  23:08:12  jraja (Jarno Tapio Rajahalme)
  34.  * Changed timer_init() to return signal mask.
  35.  * 
  36.  * Revision 1.7  93/03/10  22:07:07  22:07:07  jraja (Jarno Tapio Rajahalme)
  37.  * Made timeoutRequest handling more elegant.
  38.  * 
  39.  * Revision 1.6  93/03/05  21:11:13  21:11:13  jraja (Jarno Tapio Rajahalme)
  40.  * Fixed includes (again).
  41.  * 
  42.  * Revision 1.5  93/03/05  12:30:59  12:30:59  jraja (Jarno Tapio Rajahalme)
  43.  * Removed #if __GNUC -stuff since TimerBase is now Library in GNUC, too.
  44.  * 
  45.  * Revision 1.4  93/03/05  03:26:12  03:26:12  ppessi (Pekka Pessi)
  46.  * Compiles with SASC. Initial test version.
  47.  * 
  48.  * Revision 1.3  93/02/26  11:06:13  11:06:13  jraja (Jarno Tapio Rajahalme)
  49.  * Changed amiga.lib functions (CreatePort, DeletePort, CreateExtIO and 
  50.  * DeleteExtIO) to exec V36 equivalents (CreateMsgPort, DeleteMsgPort, 
  51.  * CreateIORequest and DeleteIORequest).
  52.  * 
  53.  * Revision 1.2  93/02/24  12:53:09  12:53:09  jraja (Jarno Tapio Rajahalme)
  54.  * Changed init to remember if initialized.
  55.  * 
  56.  * Revision 1.1  93/02/04  18:58:40  18:58:40  jraja (Jarno Tapio Rajahalme)
  57.  * Initial revision
  58.  * 
  59.  */
  60.  
  61. #include <conf.h>
  62.  
  63. #include <sys/param.h>
  64. #include <sys/systm.h>
  65. #include <sys/synch.h>
  66. #include <sys/syslog.h>
  67. #include <sys/socket.h>
  68. #include <sys/socketvar.h>
  69. #include <sys/protosw.h>    /* for protocol timeouts */
  70. #include <net/if.h>        /* for if timeout */
  71. #include <netinet/in.h>
  72. #include <net/sana2arp.h>    /* for arp timeout */
  73.  
  74. #include <kern/amiga_includes.h>
  75. #include <kern/amiga_time.h>
  76.  
  77. /*
  78.  * include prototypes for timeout functions
  79.  */
  80. #include <net/if_protos.h>              /* if_slowtimo() */
  81. #include <kern/uipc_domain_protos.h>    /* pfslowtimo(), pffasttimo() */
  82.  
  83. /*
  84.  * Global timer base pointer used throughout the code.
  85.  * Commodore says that same base should not be used by different task,
  86.  * so API users should have their own base pointer.
  87.  */
  88. struct Library     *TimerBase = NULL;
  89.  
  90. static struct MsgPort     *timerport = NULL;     /* Timer message reply port */
  91. static struct timerequest *timerIORequest = NULL; /* template IORequest */
  92.  
  93. /*
  94.  * timeoutrequest pointers for all the timeouts
  95.  */
  96. static struct timeoutRequest *ifTimer = NULL,
  97.   *arpTimer = NULL, 
  98.   *protoSlowTimer = NULL, 
  99.   *protoFastTimer = NULL;
  100.  
  101. static BOOL can_send_timeouts = FALSE; 
  102.  
  103. /*
  104.  * Initialize the timer. This MUST be called before any Timer functions are
  105.  * used (including get_time() and microtime() which use GetSysTime())
  106.  * (see sys/time.h).
  107.  *
  108.  * timerIORequest is used as a template from which all needed timer
  109.  * IO messages are copied. The command field of the request is initialized to
  110.  * TR_ADDREQUEST. Requests node type is initialized to NT_UNKNOWN for us
  111.  * to be able to recognize if it has been used.
  112.  *
  113.  * Note that we need to check manually the version of the opened device. The 
  114.  * version number must be at least 36 since we use the GetSysTime() function
  115.  * which is not defined in earlier versions.
  116.  *
  117.  * This initializes all the needed timeoutrequests too.
  118.  */
  119. ULONG
  120. timer_init(void)
  121. {
  122.   LONG error;
  123.  
  124.   /*
  125.    * Return success if already initialized
  126.    */
  127.   if (timerport != NULL)
  128.     return TRUE;
  129.  
  130.   /*
  131.    * allocate and initialize the timer message reply port
  132.    */
  133.   timerport = CreateMsgPort();
  134.   if (timerport != NULL) {
  135.     /*
  136.      * allocate and initialize the template message structure
  137.      */
  138.     timerIORequest = (struct timerequest *)
  139.       CreateIORequest(timerport, sizeof(struct timerequest));
  140.     if (timerIORequest != NULL) {
  141.       error = OpenDevice(TIMERNAME, UNIT_VBLANK, 
  142.              (struct IORequest *)timerIORequest, 0);
  143.       if (error == 0) {
  144.     /*
  145.      * Make sure that we got at least V36 timer, since we use some
  146.      * functions defined only in V36 and later.
  147.      */
  148.     if ((timerIORequest->tr_node.io_Device)->dd_Library.lib_Version >= 36) {
  149.       /*
  150.        * initialize TimerBase from timerIORequest
  151.        */
  152.       TimerBase = (struct Library *)timerIORequest->tr_node.io_Device;
  153.       /*
  154.        * Initialize some fields of the IO request to common values
  155.        */
  156.       timerIORequest->tr_node.io_Command = TR_ADDREQUEST;
  157.       /*
  158.        * NT_UNKNOWN means unused, too (see note on exec/nodes.h)
  159.        */
  160.       timerIORequest->tr_node.io_Message.mn_Node.ln_Type = NT_UNKNOWN;
  161.  
  162.       /*
  163.        * create timeout requests for all timeouts;
  164.        */
  165.       ifTimer = createTimeoutRequest(if_slowtimo, 1 / IFNET_SLOWHZ, 0); 
  166.       arpTimer = createTimeoutRequest(arptimer, ARPT_AGE, 0); 
  167.       protoSlowTimer = createTimeoutRequest(pfslowtimo, 0, 1000000 / PR_SLOWHZ); 
  168.       protoFastTimer = createTimeoutRequest(pffasttimo, 0, 1000000 / PR_FASTHZ); 
  169.       if (protoFastTimer && protoSlowTimer && arpTimer && ifTimer) {
  170.         can_send_timeouts = TRUE;
  171.         return (ULONG)(1 << timerport->mp_SigBit);
  172.       }
  173.     }
  174.       }
  175.     }
  176.   }
  177.   /*
  178.    * clean all in case of any error
  179.    */
  180.   timer_deinit();
  181.  
  182.   return (0);
  183. }
  184.  
  185. /*
  186.  * Deinitialize the timer.
  187.  * The requests are cancelled first. 
  188.  */
  189. void
  190. timer_deinit(void)
  191. {
  192.   can_send_timeouts = FALSE;
  193.  
  194.   if (protoFastTimer)
  195.     deleteTimeoutRequest(protoFastTimer);
  196.   if (protoSlowTimer)
  197.     deleteTimeoutRequest(protoSlowTimer);
  198.   if (arpTimer)
  199.     deleteTimeoutRequest(arpTimer);
  200.   if (ifTimer)
  201.     deleteTimeoutRequest(ifTimer);
  202.  
  203.   if (timerIORequest) {
  204.     TimerBase = NULL;
  205.     if (timerIORequest->tr_node.io_Device != NULL)
  206.       CloseDevice((struct IORequest *)timerIORequest);
  207.     DeleteIORequest((struct IORequest *)timerIORequest);
  208.     timerIORequest = NULL;
  209.   }
  210.   if (timerport) {
  211.     DeleteMsgPort(timerport);
  212.     timerport = NULL;
  213.   }
  214. }
  215.  
  216. /*
  217.  * Function to send all the timeout requests when everything is initialized
  218.  * DON'T even try to call this function otherwise!
  219.  */
  220. void
  221. timer_send(void)
  222. {
  223.   if (can_send_timeouts != FALSE) {
  224.     /*
  225.      * Start timeout requests
  226.      */
  227.     sendTimeoutRequest(ifTimer);
  228.     sendTimeoutRequest(arpTimer);
  229.     sendTimeoutRequest(protoSlowTimer);
  230.     sendTimeoutRequest(protoFastTimer);
  231.  
  232.     can_send_timeouts = FALSE;
  233.   }
  234. }
  235.  
  236. /*
  237.  * functions to create new timeoutRequest (after timer is initialized!)
  238.  */
  239. struct timeoutRequest *
  240. createTimeoutRequest(TimerCallback_t fun, 
  241.              ULONG seconds, ULONG micros)
  242. {
  243.   struct timeoutRequest *tr;
  244. #if DIAGNOSTIC
  245.   /*
  246.    * sanity check the micros value
  247.    */
  248.   if (micros >= 1000000) {
  249.     log(LOG_ERR, "More than 1000000 microseconds in initTimeoutRequest()\n");
  250.     return NULL;
  251.   }
  252. #endif
  253.  
  254.   /*
  255.    * allocate IO request
  256.    */
  257.   tr = CreateIORequest(timerport, sizeof(*tr));
  258.   if (tr == NULL)
  259.     return NULL;
  260.  
  261.   /*
  262.    * copy initial values from the initialized timerrequest
  263.    */
  264.  
  265.   /* Node */
  266.   tr->timeout_request.tr_node.io_Message.mn_Node.ln_Type = 
  267.     timerIORequest->tr_node.io_Message.mn_Node.ln_Type;
  268.   tr->timeout_request.tr_node.io_Message.mn_Node.ln_Pri = 
  269.     timerIORequest->tr_node.io_Message.mn_Node.ln_Pri;
  270.   tr->timeout_request.tr_node.io_Message.mn_Node.ln_Name = 
  271.     timerIORequest->tr_node.io_Message.mn_Node.ln_Name;
  272.  
  273.   /* Message */
  274.   tr->timeout_request.tr_node.io_Message.mn_ReplyPort = 
  275.     timerIORequest->tr_node.io_Message.mn_ReplyPort;
  276.  
  277.   /* IORequest */
  278.   tr->timeout_request.tr_node.io_Device = timerIORequest->tr_node.io_Device;
  279.   tr->timeout_request.tr_node.io_Unit = timerIORequest->tr_node.io_Unit;
  280.   tr->timeout_request.tr_node.io_Command = timerIORequest->tr_node.io_Command;
  281.   tr->timeout_request.tr_node.io_Flags = timerIORequest->tr_node.io_Flags;
  282.  
  283.   /*
  284.    * set our own fields
  285.    */
  286.   tr->timeout_timeval.tv_secs = seconds;
  287.   tr->timeout_timeval.tv_micro = micros;
  288.   tr->timeout_function = fun;
  289.  
  290.   return tr;
  291. }
  292.  
  293. void 
  294. deleteTimeoutRequest(struct timeoutRequest *tr)
  295. {
  296.   /*
  297.    * Abort the request if ever used
  298.    */
  299.   if (((struct Node *)tr)->ln_Type != NT_UNKNOWN) {
  300.     AbortIO((struct IORequest *)tr);
  301.     WaitIO((struct IORequest *)tr);
  302.     /*
  303.      * Make sure the signal gets cleared
  304.      */
  305.     SetSignal(0, 1 << timerport->mp_SigBit);
  306.   }
  307.   /*
  308.    * free the request
  309.    */
  310.   DeleteIORequest(tr);
  311. }
  312.  
  313. BOOL timer_poll(VOID)
  314. {
  315.   struct timeoutRequest *timerReply;
  316.  
  317.   /*
  318.    * Get all messages from the timer reply port.
  319.    */
  320.   if (timerReply = (struct timeoutRequest *)GetMsg(timerport)) {
  321.     /*
  322.      * enter softclock interrupt level
  323.      */
  324.     spl_t s = splsoftclock();
  325.     /*
  326.      * handle the timeout
  327.      */
  328.     handleTimeoutRequest(timerReply);
  329.     /*
  330.      * restart timeout request
  331.      */
  332.     sendTimeoutRequest(timerReply);
  333.     /*
  334.      * restore previous interrupt level
  335.      */
  336.     splx(s);
  337.  
  338.     return TRUE;
  339.   }
  340.  
  341.   return FALSE;
  342. }
  343.